
 /***************************************************** 
 * 
 * rcoC.nc
 * 
 * implements waiting causal broadcasts using rb
 * 
 *
 * 2010-02-25    Valentin Ecker  init
 *
 ******************************************************/

#include "CausalChat.h"

module rco {
  uses interface Leds;
  uses interface Packet;
  uses interface AMPacket;
  uses interface AMSend;
  uses interface Receive;
  uses interface SplitControl as AMControl;
  
  provides interface Rco;

}
implementation {

    message_t pkt;
    bool busy;
    bool initialized = FALSE;
    uint16_t nodeid;
    uint16_t vc[MAX_NODES];
    rco_msg_t * rco_queue[MAX_RCO_QUEUE];

    command void Rco.init()
    {
        int i;

        if(TOS_NODE_ID <= MAX_NODES)
        { nodeid = TOS_NODE_ID; }
        else
        { nodeid = 0; } /* TODO: ret err */

        rco_queue[0] = (rco_msg_t*) 0;
        
        for(i=0;i<MAX_NODES;i++)
        { vc[i] = 0; }

        busy = FALSE;

        call AMControl.start();

        initialized = TRUE;
    }

    command void Rco.broadcast(uint8_t* msg, uint16_t len)
    {
        if(!initialized)
            return;

        /* TODO: call rco.deliver */
        if (!busy) 
        {
            rco_msg_t* rco_payload = (rco_msg_t*)(call Packet.getPayload(&pkt, sizeof(rco_msg_t)));
            if (&pkt == NULL) 
            { return; }
            rco_payload->nodeid = nodeid;
            rco_payload->vc = vc[nodeid];
            if( len > MSG_LENGTH )
            { len = MSG_LENGTH; }
            memcpy(rco_payload->msg, msg, len);
            rco_payload->msg_len = len;
        if (call AMSend.send(AM_BROADCAST_ADDR, &pkt, sizeof(rco_msg_t)) == SUCCESS) 
            { busy = TRUE; }
        }
        vc[nodeid]++;
    }
  
    event void AMSend.sendDone(message_t* msg, error_t err)
    {
        if(!initialized)
            return;

        if (&pkt == msg)
        { busy = FALSE; }
    }

    event void AMControl.stopDone(error_t err) {
    }

    event void AMControl.startDone(error_t err)
    {
        if (err == SUCCESS)
        { }
        else 
        { call AMControl.start(); }
    }

    event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len)
    {
        rco_msg_t* rco_msg_container = (rco_msg_t*)payload;
        signal Rco.deliver(rco_msg_container->nodeid, rco_msg_container->msg_len,
                           rco_msg_container->vc, (char *)rco_msg_container->msg);
        return msg;
    }



}
